﻿using System;
using System.Text.RegularExpressions;
using WSKnowledge.WSHelpers.DesignByContract;

namespace WSKnowledge.WSHelpers
{
	public static class StringExtensions
	{
		private static void ValidateLength(int length)
		{
			Check.Require(length > 0, "expected string length must be greater than zero");
		}

		public static bool IsNull(this string input)
		{
			return (input == null);
		}

		public static bool IsEmpty(this string input)
		{
			return (input == String.Empty);
		}

		public static bool IsNullOrEmpty(this string input)
		{
			return (String.IsNullOrEmpty(input) == true);
		}

		public static bool IsNotEmpty(this string input)
		{
			return !input.IsNullOrEmpty();
		}

		public static bool IsLessThan(this string input, int length)
		{
			ValidateLength(length);
			return (input.IsNullOrEmpty()) ? true : (input.Length < length);
		}

		public static bool IsNotLessThan(this string input, int length)
		{
			ValidateLength(length);
			return input.IsGreaterThanOrEquals(length);
		}

		public static bool IsLessThanOrEquals(this string input, int length)
		{
			ValidateLength(length);
			return (input.IsNullOrEmpty()) ? true : (input.Length <= length);
		}

		public static bool IsExactly(this string input, int length)
		{
			ValidateLength(length);
			return (input.IsNullOrEmpty() == true) ? false : (input.Length == length);
		}

		public static bool IsGreaterThan(this string input, int length)
		{
			ValidateLength(length);
			return (input.IsNullOrEmpty() == true) ? false : (input.Length > length);
		}

		public static bool IsGreaterThanOrEquals(this string input, int length)
		{
			ValidateLength(length);
			return (input.IsNullOrEmpty() == true) ? false : (input.Length >= length);
		}

		public static bool IsNotGreaterThan(this string input, int length)
		{
			ValidateLength(length);
			return input.IsLessThanOrEquals(length);
		}

		public static bool IsBetween(this string input, int minLength, int maxLength)
		{
			ValidateLength(minLength);
			ValidateLength(maxLength);

			return (input.IsGreaterThanOrEquals(minLength)
				&& input.IsLessThanOrEquals(maxLength)) ? true : false;
		}

		public static bool IsMatch(this string input, string pattern)
		{
			Regex r = new Regex(pattern);
			return r.IsMatch(input);
		}

		public static bool IsEmailAddress(this string input)
		{
			// for pattern refer to http://regexlib.com/DisplayPatterns.aspx
			// for maximum length refer to http://email.about.com/od/emailbehindthescenes/f/address_length.htm

			Check.Require(input.IsLessThanOrEquals(320));

			return input.IsMatch(@"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$");
		}

		public static string ReplaceArgs(this string input, params object[] args)
		{
			return String.Format(input, args);
		}

		public static string AsSeparateWords(this string pascalString)
		{
			String result = pascalString;
			result = Regex.Replace(result, "([^A-Z])([A-Z])", "$1 $2").Trim();
			result = Regex.Replace(result, "([A-Z])([A-Z])([^A-Z])", "$1 $2$3").Trim();
			result = Regex.Replace(result, "([A-Za-z])([0-9])", "$1 $2").Trim();
			result = Regex.Replace(result, "([0-9])([A-Za-z])", "$1 $2").Trim();
			return result;
		}

		public static string AsOracleCase(this string pascalString)
		{
			string result = pascalString;
			result = Regex.Replace(result, "([^A-Z])([A-Z])", "$1_$2").Trim();
			result = Regex.Replace(result, "([A-Z])([A-Z])([^A-Z])", "$1_$2$3").Trim();
			result = Regex.Replace(result, "([A-Za-z])([0-9])", "$1_$2").Trim();
			result = Regex.Replace(result, "([0-9])([A-Za-z])", "$1_$2").Trim();
			return result.ToUpper();
		}
	}
}
